from __future__ import with_statement

from OpenGL.GL import *

class gl_matrix(object):
    """
    DOCUMENT ME!  i'm just glPushMatrix()/glPopMatrix()
    """
    def __enter__(self):
        glPushMatrix()
    def __exit__(self, type_, value, tb):
        if tb is None:
            glPopMatrix()
        else:
            # nothing we can do, except:
            return False  # = reraise

class gl_group(object):
    """
    DOCUMENT ME!  i'm just glBegin(mode)/glEnd()
    """
    def __init__(self, mode):
        self.mode = mode
    def __enter__(self):
        glBegin(self.mode)
    def __exit__(self, type_, value, tb):
        if tb is None:
            glEnd()
        else:
            # nothing we can do, except:
            return False  # = reraise

class gl_list(object):
    """
    DOCUMENT ME!  i'm just glNewList(number,mode)/glEndList()
    (then glCallList(n) to use it)

    NOTE: you still need number=glGenLists(1) before calling this,
    because context managers can't return values (!).
    """
    def __init__(self, mode):
        self.mode = mode
    def __enter__(self):
        # allocate space for a new display list
        self.number = glGenLists(1)
        if self.number == 0:
            raise RuntimeError("can't allocate display list")

        # make a new list with it
        glNewList(self.number, self.mode)

        # return it, so you know what it is for later
        return self.number
    def __exit__(self, type_, value, tb):
        if tb is None:
            glEndList()
        else:
            # nothing we can do, except:
            return False  # = reraise

## TODO: split gl_list into two:
## - gl_new_list(mode) as number
## - gl_list(number, mode)
## or: make it one, with mode first, and number=None by default.


##
## COMPLETELY EXPERIMENTAL: (and not even tested)
##

# (NOTE: the opengl docs call them "capabilities")
class gl_features(object):
    """
    DOCUMENT ME!  i'm just glEnable/glDisable
    """
    def __init__(self, **features):
        self.features = features  # save as dict
    def __enter__(self):
        # save the original state of each feature
        self.oldfeatures = {}
        for key in self.features:
            self.oldfeatures[key] = glIsEnabled(key)

        # enable/disable features as requested
        for key,value in self.features.items():
            if value:
                glEnable(key)
            else:
                glDisable(key)
    def __exit__(self, type_, value, tb):
        if tb is None:
            # reset features to their original state
            for key,value in self.oldfeatures.items():
                if value:
                    glEnable(key)
                else:
                    glDisable(key)
        else:
            # nothing we can do, except:
            return False  # = reraise

## of course, if you use this inside a GL_COMPILE block,
## the fancy save/change/restore i do will go to waste.
## is this a useful abstraction?
